package org.tp.edifact.syntax;

import static org.junit.Assert.*;

import org.junit.Test;
import org.tp.exceptions.XInvalidArgumentValueError;
import org.tp.exceptions.XNullArgumentError;

public class TestCustomV3ServCharSet {
   private static final char[][] INVALID_CHARACTER_SETS = 
      {
         {},                                          //| Empty
         {':'},                                       //| One element.
         {':', '+'},                                  //| Two elements.
         {':', '+', '.'},                             //| Three elements.
         {':', '+', '.', '?'},                        //| Four elements.
         {':', '+', '.', '?', ' '},                   //| Five elements.
         {':', '+', '.', '?', ' ', '\'', '*'},        //| Seven elements.
         {':', '+', '.', '?', ' ', '\'', '*', '%'},   //| Eight elements.
         {':', '+', '.', '?', ' ', ':'},              //| First and last duplicated.
         {':', '+', '.', '?', '+', '\''},             //| 2 & 5 duplicated.
         {':', '+', '.', '.', ' ', '\''}              //| 3 & 4 duplicated.
      };

   private static final char[] CUSTOM_SET = {'\'', '*', '.', ':', ' ', '?'}; 
   private static final char[] SERVICE_CHARACTERS = {'\'', '*', ':', '?'};
   private static final ECharacterClass[] SERVICE_CHARACTER_IDS = {
      ECharacterClass.COMPONENT_DATA_ELEMENT_SEPARATOR,
      ECharacterClass.DATA_ELEMENT_SEPARATOR,
      ECharacterClass.RELEASE_INDICATION,
      ECharacterClass.SEGMENT_TERMINATOR
   };

   @Test
   public void testConstructor() {
      for (int i = 0; i < INVALID_CHARACTER_SETS.length; i++) {
         try {
            CustomV3ServCharSet csc = new CustomV3ServCharSet(INVALID_CHARACTER_SETS[i]);
            fail("Must raise XInvalidArgumentValueError.");
         }
         catch (XInvalidArgumentValueError x) {
         }
         catch (Throwable t) {
            fail("Unexpected exception " + t);
         }
      }
      
      try {
         CustomV3ServCharSet cs1 = new CustomV3ServCharSet(null); 
         fail("Must raise XNullArgumentError.");
      }
      catch (XNullArgumentError x) {
      }
      catch (Throwable t) {
         fail("Unexpected exception " + t);
      }
      
      try {
         CustomV3ServCharSet cs1 = new CustomV3ServCharSet(CUSTOM_SET); 
      }
      catch (Throwable t) {
         fail("Unexpected exception " + t);
      }
      
   }
   
   
   @Test
   public void testIsServiceCharacter() {
      CustomV3ServCharSet scs = new CustomV3ServCharSet(CUSTOM_SET);
      int serviceCharacterCount = 0;
      
      char c;
      
      for(int i = 0; i <= 255; i++) {
         c = (char) (i & 0xff);

         if (scs.isServiceCharacter(c)) {
            serviceCharacterCount++;
         }
      }
      
      //| Must be 4 service characters.
      
      assertEquals(
            "Wrong number of service characters",
            SERVICE_CHARACTERS.length,
            serviceCharacterCount);  
      
      //| Check that service characters are actually service characters.
      
      for (int i = 0; i < SERVICE_CHARACTERS.length; i++) {
         assertTrue(
               "Character " + SERVICE_CHARACTERS[i] + " shall be a service character.",
               scs.isServiceCharacter(SERVICE_CHARACTERS[i]));           
      }
   }
   
   @Test
   public void testGetServiceCharacterIdentifier() {
      CustomV3ServCharSet scs = new CustomV3ServCharSet(CUSTOM_SET);
      
      for (int i = 0; i < SERVICE_CHARACTERS.length; i++) {
         assertEquals(
               "Wrong character identifier for character: " + (int) SERVICE_CHARACTERS[i],
               SERVICE_CHARACTER_IDS[i],
               scs.getCharacterClass(SERVICE_CHARACTERS[i]));
      }
      
      char c;
      
      for(int i = 0; i <= 255; i++) {
         c = (char) (i & 0xff);

         if (!scs.isServiceCharacter(c)) {
            assertEquals(
                  "Wrong service character: " + c,
                  ECharacterClass.DATA_CHARACTER,
                  scs.getCharacterClass(c));
         }
      }
   }
   
   @Test
   public void testGetServiceCharacter() {
      CustomV3ServCharSet scs = new CustomV3ServCharSet(CUSTOM_SET);

      for (int i = 0; i < SERVICE_CHARACTER_IDS.length; i++) {
         assertEquals(
               "Wrong service character identifier: " + SERVICE_CHARACTER_IDS[i],
               SERVICE_CHARACTERS[i],
               scs.getServiceCharacter(SERVICE_CHARACTER_IDS[i]));
         
      }
   }
   
   @Test
   public void testGetServiceCharacterSet() {
      CustomV3ServCharSet scs = new CustomV3ServCharSet(CUSTOM_SET);
      
      char[] s = scs.getServiceCharacterSet();
      
      for (int i = 0; i < s.length; i++) {
         assertEquals(
               "Wrong service character at position: "
                  + i,
               CUSTOM_SET[i],
               s[i]);
      }
         
      char[] s2 = scs.getServiceCharacterSet();
      
      assertNotEquals(
            "Same array object returned",
            s,
            s2);
      
      s[5] = '@';
      s2 = scs.getServiceCharacterSet();

      assertNotEquals(
            "Changed object contents.",
            s[5],
            s2[5]);
   }
   
   @Test
   public void testHasMethods() {
      CustomV3ServCharSet scs = new CustomV3ServCharSet(CUSTOM_SET);

      assertTrue(
            "This character set must have release indicator.",
            scs.hasReleaseIndicator());

      assertFalse(
            "This character set must not have repetition separator.",
            scs.hasRepetitionSeparator());
   }
   
}
